package com.example.upload.tool;

import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

public final class DateUtils {

    public static final SimpleDateFormat FORMAT_YYYY_MM_DD = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat longDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final SimpleDateFormat longDateFormatM = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    public static final SimpleDateFormat formatyyMM = new SimpleDateFormat("yyMM");
    public static final SimpleDateFormat format_ddHHmmss = new SimpleDateFormat("ddHHmmss");

    public static final List<String> KEYS = Arrays.asList("全部", "今天", "三天内", "一周内", "一个月内", "三个月内", "半年内");

    public static final String KEY_START = "start";

    public static final String KEY_END = "end";

    /**
     * @return 自纪元时间以来的毫秒数
     */
    public static Long getEpochMilliSecond() {
        return System.currentTimeMillis();
    }

    /**
     * @return 自纪元时间以来的秒数
     */
    public static long getEpochSecond() {
        return Instant.now().getEpochSecond();
    }

    /**
     * 根据类型获取具体类型时间
     *
     * @param calendarType
     * @param num          +- ：+为指定日期的后num(年月日)；-为指定日期的前num(年月日)
     * @return
     */
    public static int getDateNumberByCalendar(int calendarType, int num) {
        Calendar cale = Calendar.getInstance();
        return cale.get(calendarType) + num;
    }

    /**
     * 获取指定某一天的开始时间戳
     */
    public static Long getDailyBegin(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取指定某一天的结束时间戳
     */
    public static Long getDailyEnd(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTimeInMillis();
    }

    public static long getMonthBegin(long time) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time);
        //设置为1号,当前日期既为本月第一天
        c.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        c.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        c.set(Calendar.MINUTE, 0);
        //将秒至0
        c.set(Calendar.SECOND, 0);
        //将毫秒至0
        c.set(Calendar.MILLISECOND, 0);
        // 获取本月第一天的时间戳
        return c.getTimeInMillis();
    }

    /**
     * 获取指定时间戳所在月份结束的时间戳/秒
     *
     * @return
     */
    public static Long getMonthEnd(long time) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time);

        //设置为当月最后一天
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        //将小时至23
        c.set(Calendar.HOUR_OF_DAY, 23);
        //将分钟至59
        c.set(Calendar.MINUTE, 59);
        //将秒至59
        c.set(Calendar.SECOND, 59);
        //将毫秒至999
        c.set(Calendar.MILLISECOND, 999);
        // 获取本月最后一天的时间戳
        return c.getTimeInMillis();
    }


    public static Map<String, String> getDateInterval(String key) {
        if (!KEYS.contains(key)) {
            return null;
        }
        Map<String, String> result = new HashMap<String, String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String start = "";
        String end = "";

        if (key.equals(KEYS.get(1))) {// 今天
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.set(Calendar.HOUR_OF_DAY, 0);
            ca.set(Calendar.MINUTE, 0);
            ca.set(Calendar.SECOND, 0);
            String date = sdf.format(ca.getTime());
            start = date;

        }
        if (key.equals(KEYS.get(2))) {// 三天内
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.add(Calendar.DAY_OF_MONTH, -3);
            start = sdf.format(ca.getTime());
        }
        if (key.equals(KEYS.get(3))) {// 一周内
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.add(Calendar.DAY_OF_MONTH, -7);
            start = sdf.format(ca.getTime());
        }
        if (key.equals(KEYS.get(4))) {// 一个月内
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.add(Calendar.DAY_OF_MONTH, -30);
            start = sdf.format(ca.getTime());
        }
        if (key.equals(KEYS.get(5))) {// 三个月内
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.add(Calendar.DAY_OF_MONTH, -90);
            start = sdf.format(ca.getTime());
        }
        if (key.equals(KEYS.get(6))) {// 半年内
            Calendar ca = Calendar.getInstance();
            end = sdf.format(ca.getTime());
            ca.add(Calendar.DAY_OF_MONTH, -180);
            start = sdf.format(ca.getTime());
        }
        result.put(KEY_START, start);
        result.put(KEY_END, end);
        return result;

    }

    public static Date formatDate(String dateStr) {
        Date d = null;
        try {
            d = longDateFormat.parse(dateStr);
        } catch (Exception localException) {
        }
        return d;
    }

    public static Date formatDate(String dateStr, String pattern) {
        Date d = null;
        try {
            d = new SimpleDateFormat(pattern).parse(dateStr);
        } catch (Exception localException) {
        }
        return d;
    }

    public static String formatDate(Date date, String pattern) {
        SimpleDateFormat longDateFormatTemp = null;
        try {
            if (StringUtils.isEmpty(pattern)) {
                longDateFormatTemp = longDateFormat;
            } else {
                longDateFormatTemp = new SimpleDateFormat(pattern);
            }
            return longDateFormatTemp.format(date);
        } catch (Exception localException) {
            return null;
        }

    }

    /**
     * 获取指定时间的前/后dayNum小时的日期
     *
     * @param date   指定时间
     * @param dayNum +- ：+为指定日期的后dayNun小时；-为指定日期的前dayNun小时
     * @return
     */
    public static Date getDateByHour(Date date, int dayNum) {
        if (date != null && dayNum != 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.HOUR, dayNum);
            date = calendar.getTime();
        }
        return date;
    }

    /**
     * 将Unix时间戳格式化为指定格式的日期字符串
     *
     * @param timestamp Unix时间戳
     * @param pattern   日期格式
     * @return 指定格式的日期字符串
     */
    public static String format(long timestamp, String pattern) {
        Date date = parse(timestamp);
        return getDateFormatter(pattern).format(date);
    }

    /**
     * 将Unix时间戳转换为日期
     *
     * @param timestamp Unix时间戳
     * @return 日期
     */
    public static Date parse(long timestamp) {
        return new Date(timestamp);
    }

    /**
     * 获取日期格式化对象
     *
     * @param pattern 格式
     * @return 日期格式化对象
     */
    private static DateFormat getDateFormatter(String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setTimeZone(TimeZone.getDefault());
        return sdf;
    }


    /**
     * 获取当前时间是当前月份的第几周
     *
     * @param currentDate 当前时间
     * @return
     */
    public static String getTheWeekOfCurrentMonth(LocalDate currentDate) {


        LocalDate firstDayOfMonth = currentDate.withDayOfMonth(1);
        // 获取当前月份的最后一天
        LocalDate lastDayOfMonth = currentDate.with(TemporalAdjusters.lastDayOfMonth());
        DayOfWeek firstDayOfWeek = firstDayOfMonth.getDayOfWeek();

        // 跨月第一周的开始日期
        LocalDate startOfWeek = firstDayOfMonth.minusDays(firstDayOfWeek.getValue() - 1);
        LocalDate localDate = startOfWeek.with(TemporalAdjusters.lastDayOfMonth());

        //跨了几天
        int days = 0;
        // 如果跨月，向前推一周
        if (startOfWeek.getMonth() != firstDayOfMonth.getMonth()) {
            days = (localDate.getDayOfMonth() - startOfWeek.getDayOfMonth()) + 1;
            startOfWeek = startOfWeek.plusDays(7);

            if (currentDate.isBefore(startOfWeek) ) {
                return currentDate.getMonth().ordinal() + 1 + "月第1周";
            } else {
                //有多少周
                int week = (lastDayOfMonth.getDayOfMonth() + days) / 7;

                int weekOfMonth = (currentDate.getDayOfMonth() - startOfWeek.getDayOfMonth()) / 7 + 2;
                if (weekOfMonth <= week) {
                    return currentDate.getMonth().ordinal() + 1 + "月第" + weekOfMonth + "周";
                } else {
                    return currentDate.getMonth().plus(1).ordinal() + 1 + "月第1周";
                }

            }
        } else {
            //有多少周
            int week = (lastDayOfMonth.getDayOfMonth() + days) / 7;

            int weekOfMonth = (currentDate.getDayOfMonth() - startOfWeek.getDayOfMonth()) / 7 + 1;
            if (weekOfMonth <= week) {
                return currentDate.getMonth().ordinal() + 1 + "月第" + weekOfMonth + "周";
            } else {
                return currentDate.getMonth().plus(1).ordinal() + 1 + "月第1周";
            }
        }
    }



    /**
     * 获取凌晨时间戳
     *
     * @param localDate
     * @return
     */
    public static Long getDayOfStartTime(LocalDate localDate) {

        // 将LocalDate与凌晨的时间（00:00）结合，创建LocalDateTime
        LocalDateTime midnight = localDate.atStartOfDay();

        // 将LocalDateTime转换为ZonedDateTime，以便获取特定时区的时间戳
        ZonedDateTime zdt = midnight.atZone(ZoneId.systemDefault());

        // 将ZonedDateTime转换为时间戳（毫秒）
        long timestamp = zdt.toInstant().toEpochMilli();

        // 输出结果
        return timestamp;
    }


    public static LocalDate getLocalDateByTimestamp(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate();
    }


    public static List<LocalDate> getEverDay(Long startTime, Long endTime) {
        List<LocalDate> result = new ArrayList<>();
        LocalDate startLocalDate = DateUtils.getLocalDateByTimestamp(startTime);

        LocalDate endLocalDate = DateUtils.getLocalDateByTimestamp(endTime);
        while (true) {
            if (startLocalDate.isBefore(endLocalDate)) {
                result.add(startLocalDate);
                startLocalDate = startLocalDate.plusDays(1);
            } else {
                result.add(startLocalDate);
                break;
            }
        }
        return result;
    }



    public static void main(String[] args) {
		/*LocalDate localDate = LocalDate.now();
		localDate.plusDays(1);
		System.out.println(localDate.toString());
		System.out.println(localDate.getYear()+"-"+localDate.getMonthValue());
		getEverDay(1706716800000L,1710432000000L);

		getEverMonth(1706716800000L,1710432000000L);*/
        getTheWeekOfCurrentMonth(LocalDate.parse("2023-12-27"));

    }


}
